{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Conformation & Protein Geometry"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "在前一个章节中，我们已经介绍了在Rosetta中，Residue对象是描述蛋白质的基本单元，许多独立的Residue被用于描述蛋白质的几何结构和高级构象。\n",
    "这些细微的构象变化的度量就是由原子间的键长、键角，二面角等一系列的具体参数构成。在PyRosetta中, Pose中这些几何构象的参数由Conformation对象负责记录。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 1.几何构象\n",
    "蛋白质是由多个氨基酸通过脱水缩合的方式形成肽键共价连接。因此对于天然氨基酸而言。骨架最重要的两个二面角就是phi和psi角，而omega由于肽键平面一般处于0或180°附近。对于不同的氨基酸侧链，每个Residue含有若干个chi角。这些二面角组成了Rosetta对构象采样的基本几何参数。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "![title](./img/phipsiomega.png)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "PyRosetta-4 2020 [Rosetta PyRosetta4.conda.mac.cxx11thread.serialization.python36.Release 2020.23+release.0d6f90a8cb9fa0567ca76bb71ee93bfe73340c70 2020-06-04T19:12:24] retrieved from: http://www.pyrosetta.org\n",
      "(C) Copyright Rosetta Commons Member Institutions. Created in JHU by Sergey Lyskov and PyRosetta Team.\n",
      "\u001b[0mcore.init: {0} \u001b[0mChecking for fconfig files in pwd and ./rosetta/flags\n",
      "\u001b[0mcore.init: {0} \u001b[0mRosetta version: PyRosetta4.conda.mac.cxx11thread.serialization.python36.Release r257 2020.23+release.0d6f90a8cb9 0d6f90a8cb9fa0567ca76bb71ee93bfe73340c70 http://www.pyrosetta.org 2020-06-04T19:12:24\n",
      "\u001b[0mcore.init: {0} \u001b[0mcommand: PyRosetta -ex1 -ex2aro -database /opt/miniconda3/envs/pyrosetta/lib/python3.6/site-packages/pyrosetta/database\n",
      "\u001b[0mbasic.random.init_random_generator: {0} \u001b[0m'RNG device' seed mode, using '/dev/urandom', seed=-1381307248 seed_offset=0 real_seed=-1381307248 thread_index=0\n",
      "\u001b[0mbasic.random.init_random_generator: {0} \u001b[0mRandomGenerator:init: Normal mode, seed=-1381307248 RG_type=mt19937\n",
      "\u001b[0mcore.import_pose.import_pose: {0} \u001b[0mFile './data/4jfx_peptide.pdb' automatically determined to be of type PDB\n"
     ]
    }
   ],
   "source": [
    "# 读取多肽的PDB结构\n",
    "from pyrosetta import init, pose_from_pdb\n",
    "init()\n",
    "pose = pose_from_pdb('./data/4jfx_peptide.pdb')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 1.1 基本二面角几何参数\n",
    "从pyrosetta中获取这些基本几何参数的方式非常简单:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "-148.8025511852094 157.0624491251048 157.0624491251048\n"
     ]
    }
   ],
   "source": [
    "# 获取第4号氨基酸的骨架二面角:\n",
    "phi = pose.phi(3)\n",
    "psi = pose.psi(3)\n",
    "omega = pose.psi(3)\n",
    "print(phi, psi, omega)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "也可以直接获取侧链的二面角参数:\n",
    "pose.chi(chi角编号, Residue的pose编号)即可获取。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "3\n",
      "70.4233120899352\n",
      "81.97278776078356\n",
      "-2.023205011879734e-14\n"
     ]
    }
   ],
   "source": [
    "# 获取第三号残基的chi角信息: pose.chi(chi_id:int, residue_id:int)\n",
    "chi_num = len(pose.residue(3).chi_atoms())\n",
    "print(chi_num)\n",
    "\n",
    "for chi_id in range(1, chi_num+1):\n",
    "    chi_angle = pose.chi(chi_id, 3)\n",
    "    print(chi_angle)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 1.2 调整二面角几何参数\n",
    "Pose对象中内置的几个函数非常方便地可以用于调整几何构象: set_phi, set_psi, set_omega, set_chi。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 调整骨架二面角\n",
    "pose.set_phi(3,-150)\n",
    "pose.set_phi(3,170)\n",
    "pose.dump_pdb('4jfx_peptide_conf0.pdb')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "调整构象后的多肽构象直观感受:\n",
    "![title](./img/conf.png)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 调整3号氨基酸的侧链chi1角的角度;\n",
    "pose.set_chi(1, 3, 60)\n",
    "pose.dump_pdb('4jfx_peptide_chi_conf0.pdb')\n",
    "pose.set_chi(1, 3, -60)\n",
    "pose.dump_pdb('4jfx_peptide_chi_conf1.pdb')\n",
    "pose.set_chi(1, 3, 180)\n",
    "pose.dump_pdb('4jfx_peptide_chi_conf2.pdb')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "![title](./img/chi_conf.png)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 2 化学键几何参数\n",
    "除了对构象变化依赖影响最大的二面角参数，局部的化学键键长和键角信息也储存在Conformation对象中。\n",
    "为了定位原子的信息，首先需要构建atom identifier对象，相当于创建一个ID卡，让Rosetta知道我们指定的原子是位于哪个氨基酸中的。通过AtomID，提供残基号，原子号，就可以创建atom identifier对象"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      " atomno= 1 rsd= 3   atomno= 2 rsd= 3   atomno= 3 rsd= 3   atomno= 4 rsd= 3 \n"
     ]
    }
   ],
   "source": [
    "# 获取原子间的键长、键角信息前需要构建atom identifier objects\n",
    "from pyrosetta.rosetta.core.id import AtomID\n",
    "atom1 = AtomID(1, 3)  # 3号残基的第一个原子\n",
    "atom2 = AtomID(2, 3)  # 3号残基的第二个原子\n",
    "atom3 = AtomID(3, 3)  # 3号残基的第三个原子\n",
    "atom4 = AtomID(4, 3)  # 3号残基的第四个原子\n",
    "print(atom1, atom2, atom3, atom4)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "知道原子的ID后，就可以通过conformation对象来获取键长、键角等数据了。但一般这些参数在Rosetta中键长和键角都设定为理想值，可以极大减少蛋白质构象的采样自由度空间。但注意的是，获取的键长键角必须有是“物理连接的”。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "键长:1.4632750937537378, 键角:1.9840915800459624\n"
     ]
    }
   ],
   "source": [
    "# 通过conformation层获取键长数据\n",
    "bond_length = pose.conformation().bond_length(atom1, atom2)\n",
    "\n",
    "# 通过conformation层获取键角数据(弧度)\n",
    "bond_angle = pose.conformation().bond_angle(atom1, atom2, atom3)\n",
    "\n",
    "print(f'键长:{bond_length}, 键角:{bond_angle}')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "同样原子间的键长和键角也是可以被调整的:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1.5 3.4\n"
     ]
    }
   ],
   "source": [
    "# 设置新的值:\n",
    "pose.conformation().set_bond_length( atom1, atom2, 1.5)\n",
    "pose.conformation().set_bond_angle( atom1, atom2, atom3, 3.4)\n",
    "\n",
    "# \n",
    "new_bond_length = pose.conformation().bond_length(atom1, atom2)\n",
    "new_bond_angle = pose.conformation().bond_angle(atom1, atom2, atom3)\n",
    "print(new_bond_length, new_bond_angle)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 3. 原子坐标的调整\n",
    "原子坐标的修改需要获取residue对象，并获取原子ID(atom identifier objects)。通过pose.set_xyz函数设定新的xyz坐标, 但用户一般不需要”显式“地修改原子坐标, 除非你明白这样操作的意义。此处我们沿着3个坐标轴平移所有原子3个埃的距离。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 原子坐标的修改（一般不需要这样操作）\n",
    "from pyrosetta.rosetta.numeric import xyzVector_double_t\n",
    "\n",
    "# 对所有氨基酸的所有原子的x坐标乘上一个负号:\n",
    "for residue_id in range(1, pose.total_residue()+1):\n",
    "    residue = pose.residue(residue_id) # 获取residue对象\n",
    "    for atom_id, atom in enumerate(residue.atoms()):\n",
    "        x, y, z = atom.xyz()\n",
    "\n",
    "        atom_id\n",
    "        mirror_xyz = xyzVector_double_t(x+3, y+3, z+3)  # 乘上负号.\n",
    "        atom_index = AtomID(atom_id+1, residue_id)   # 3号氨基酸的第x个原子的id\n",
    "        pose.set_xyz(atom_index, mirror_xyz) # 设置xyz坐标"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 37,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "pose.dump_pdb('trans.pdb')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "![title](./img/trans_xyz.png)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 4. 二级结构信息\n",
    "Rosetta中的二级结构信息来源于DSSP的计算。通过get_secstruct函数即可获取。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\u001b[0mprotocols.DsspMover: {0} \u001b[0mLLLLLLLL\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "vector1_char[L, L, L, L, L, L, L, L]"
      ]
     },
     "execution_count": 38,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 通过DSSP获取二级结构信息\n",
    "from pyrosetta.rosetta.protocols.membrane import get_secstruct\n",
    "get_secstruct(pose)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 进阶: 任意几何特征的获取"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "待补充。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "pyrosetta",
   "language": "python",
   "name": "pyrosetta"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.10"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
